1.【預測再驗證|UI 與版型】 昨天的 ScannerScreen 掃完要把 ScanResult 交回打開它的畫面。最常見的寫法是透過上一個 back stack entry 的 SavedStateHandle,骨架大概是這樣:
// 掃描畫面:按「完成」時
navController.previousBackStackEntry?.savedStateHandle?.set("scan_result", result)
navController.popBackStack()
// 呼叫端(例如任務明細):在自己的 composable<TaskDetailRoute> { entry -> ... } 裡
val result by entry.savedStateHandle
.getStateFlow<ScanResult?>("scan_result", null)
.collectAsStateWithLifecycle()
LaunchedEffect(result) {
result?.let {
viewModel.onScanned(it)
entry.savedStateHandle.remove<ScanResult>("scan_result")
}
}
下面每個情境,先寫下你的預測,再用實機或模擬器驗證(「開發者選項 → 不保留活動」、adb shell am kill <package> 都可以用來模擬 process 被回收):
onScanned 總共被呼叫幾次?把 remove 那行拿掉,再旋轉一次、再從背景切回來,各是幾次?ScanResult 是一個普通的 data class(沒有 Parcelable、沒有 @Serializable)。哪一步會出問題:set 的當下、App 退到背景時、還是 process 被回收後回來時?換成 @Parcelize 之後呢?savedStateHandle。會不會出問題?如果會,是在哪個時間點、什麼徵狀?你的預測依據是什麼?SavedStateHandle,而不是 entry.savedStateHandle。讀得到嗎?這兩個是不是同一個物件?previousBackStackEntry 是誰?結果送到哪裡去了?最後回答:這五個情境裡,哪幾個可以在 JVM 單元測試裡用 SavedStateHandle() 直接重現?哪幾個要起 TestNavHostController 或 instrumented test?哪幾個只能在實機驗、要寫進發版前的手動檢查清單?
我的回答:(待補)
2.【模擬面試追問|架構論述】 面試官看了你的掃描畫面設計,問:「掃描結果怎麼回到呼叫端?」你列出三種做法:
SavedStateHandle(第 1 題的寫法)。hiltViewModel(parentEntry) 拿到綁在那個圖上的同一個 ViewModel,掃描畫面把結果寫進去。@Singleton 的物件裡放 MutableSharedFlow<ScanResult>,掃描畫面送出、呼叫端收集。不看下面的大綱,依序回答面試官的追問:
NavController 就能測?ScanConfig 帶驗證函式、不做通用畫面),你預設選了其中一種。那個選擇跟今天選的回傳方式會互相牽動嗎?舉一個兩者合不來的組合。最後用兩句話收尾這場面試:你的結論,以及你願意承認的代價。
我的回答:(待補)